#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <string>
using namespace std;
using namespace cv;
Mat add_jiaoyan(Mat &image, int n);
Mat add_gaosi(Mat &image);
Mat lvboqi_junzhi(Mat &image, int size);
Mat lvboqi_zhongzhi(Mat &image, int size);
void sortArray(int *p, int length);
///////////////////////////为图像添加椒月噪声///////////
int main() {
    Mat src = imread("/home/dao/桌面/week04/src/first.png");
    Mat dst;
    cvtColor(src, dst, COLOR_BGR2GRAY);
    Mat dstResult = add_jiaoyan(dst, 10000);
    Mat srcResult = add_jiaoyan(src, 10000);
    Mat dstResultProcess01 = lvboqi_junzhi(dstResult, 3);
    Mat dstResultProcess02 = lvboqi_zhongzhi(dstResult, 3);
    // Mat dstResultProcess02;
    // medianBlur(dstResult, dstResultProcess02, 3);
    imshow("灰度图像", dst);
    imshow("原图像", src);
    imshow("添加噪声后的灰度图像", dstResult);
    imshow("添加噪声后的彩色图像", srcResult);
    imshow("均质滤波处理噪声结果", dstResultProcess01);
    imshow("中值滤波处理噪声结果", dstResultProcess02);
    waitKey(0);
}

// int main() {
//     cout << "12345" << endl;
//     Mat src = imread("/home/dao/桌面/week04/src/first.png");
//     Mat dst;
//     cvtColor(src, dst, COLOR_BGR2GRAY);
//     Mat dstResult = add_jiaoyan(dst, 10000);
//     Mat srcResult = add_jiaoyan(src, 10000);
//     imshow("灰度图像", dst);
//     imshow("原图像", src);
//     imshow("添加噪声后的灰度图像", dstResult);
//     imshow("添加噪声后的彩色图像", srcResult);

//     waitKey(0);
// }

Mat add_jiaoyan(Mat &image, int n) {
    Mat image_clone = image.clone();
    for (int k = 0; k < n / 2; k++) {
        int i = rand() % image_clone.rows;
        int j = rand() % image_clone.cols;
        int num = rand() % 2;
        if (num == 0) {
            if (image_clone.type() == CV_8UC3) {
                image_clone.at<Vec3b>(i, j)[0] = 0;
                image_clone.at<Vec3b>(i, j)[1] = 0;
                image_clone.at<Vec3b>(i, j)[2] = 0;
            } else if (image_clone.type() == CV_8UC1) {
                image_clone.at<uchar>(i, j) = 0;
            }
        } else if (num == 1) {
            if (image_clone.type() == CV_8UC3) {
                image_clone.at<Vec3b>(i, j)[0] = 1;
                image_clone.at<Vec3b>(i, j)[1] = 1;
                image_clone.at<Vec3b>(i, j)[2] = 1;
            } else if (image_clone.type() == CV_8UC1) {
                image_clone.at<uchar>(i, j) = 1;
            }
        }
    }
    return image_clone;
}

// Mat add_gaosi(Mat &image) {
//     Mat gaosi = Mat::zeros(image.rows, image.cols, image.type());
//      RNG rng;
//      if (image.type() == CV_8UC1) {
//          rng.fill(gaosi, RNG::NORMAL, 15, 30);
//     } else {
//         rng.fill(gaosi, RNG::NORMAL, 10, 25);
//     }
//     imshow("高斯模糊", gaosi);
//     Mat image_clone = image.clone();
//     image_clone = image + gaosi;
//     waitKey(0);
//     return image_clone;
// }

Mat lvboqi_junzhi(Mat &image, int size) {
    // size创建的对象常常用来存储图向的宽度与高度
    Mat image_clone = image.clone();
    //对卷及核的合理性判断
    if (size % 2 == 0) {
        cout << "请输入一个有效的尺寸" << endl;
        return image_clone;
    }
    //对原图像进行扩充
    int addH = (size - 1) / 2;  //计算扩充高度
    int addW = (size - 1) / 2;  //计算扩充高度
    Mat newimage;
    copyMakeBorder(image, newimage, addW, addW, addH, addH, BORDER_DEFAULT);

    for (int i = addH; i < image.rows + addH; i++) {
        for (int j = addW; j < image.cols + addW; j++) {
            if (image.type() == CV_8UC1) {
                int sum = 0;
                for (int m = i - addH; m <= i + addH; m++) {
                    for (int n = j - addW; n <= j + addW; n++) {
                        sum = sum + newimage.at<uchar>(m, n);
                    }
                }
                int average = sum / (size * size);
                image_clone.at<uchar>(i - addH, j - addW) = average;
            }
        }
    }
    return image_clone;
}
Mat lvboqi_zhongzhi(Mat &image, int size) {
    if (size % 2 == 0) {
        cout << "卷及核尺寸不合理" << endl;
        return image;
    }
    Mat image_clone = image.clone();
    int addH = (size - 1) / 2;
    int addW = (size - 1) / 2;
    Mat newimage;
    copyMakeBorder(image, newimage, addW, addW, addH, addH, BORDER_REFLECT_101);

    for (int i = addH; i < image.rows + addH; i++) {
        uchar *p0 = image_clone.ptr<uchar>(i - addH);
        for (int j = addW; j < image.cols + addW; j++) {
            int *pixel = new int[size * size];
            int k = 0;
            for (int m = i - addH; m <= i + addH; m++) {
                uchar *p = newimage.ptr<uchar>(m);
                for (int n = j - addW; n <= j + addW; n++) {
                    pixel[k] = p[n];
                    k++;
                }
            }
            sortArray(pixel, (size * size));
            p0[j - addW] = pixel[((size * size) - 1) / 2];
        }
    }
    return image_clone;
}
void sortArray(int *p, int length) {
    for (int i = 0; i < length - 1; i++) {
        for (int j = 1; j < length - i; j++) {
            if (p[j - 1] < p[j]) {
                int temp = p[j];
                p[j] = p[j - 1];
                p[j - 1] = temp;
            }
        }
    }
}
